package org.jawa.model;

import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.GrantedAuthorityImpl;
import org.springframework.security.userdetails.UserDetails;

@Entity
@Table(name = "user")
public class User extends BaseObject implements Serializable, UserDetails {

	private static final long serialVersionUID = -5325347818336610684L;

	private Long id;
	private String username;
	private String email;

	private String password; // required
	private String confirmPassword;
	private String userpaypwd;
	private Character validated;
	private String fullName;
	private Boolean sex;
	private String photo;
	private String country;
	private String state;
	private String city;
	private String address;
	private Double balance;
	private String draw;
	private Integer exchange;
	private Integer good;
	private Integer neutral;
	private Date regdate;
	private Integer bad;
	private Date lastlogindate;
	private Integer logins;
	private Date updatedate;
	private boolean enabled;
	private Set<Inquire> inquires = new HashSet<Inquire>(0);
	private Set<Shop> shops = new HashSet<Shop>(0);
	private Set<Product> products = new HashSet<Product>(0);
	private Set<Favorite> favorites = new HashSet<Favorite>(0);
	private Set<Auction> auctions = new HashSet<Auction>(0);
	private Set<Order> orders = new HashSet<Order>(0);

	/**
	 * Default constructor - creates a new instance with no values set.
	 */
	public User() {
	}

	/**
	 * Create a new instance and set the username.
	 * 
	 * @param username
	 *            login name for user.
	 */
	public User(final String username) {
		this.username = username;
	}

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	public Long getId() {
		return this.id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	@Column(nullable = false)
	public String getPassword() {
		return password;
	}

	@Transient
	public String getConfirmPassword() {
		return confirmPassword;
	}

	@Column(name = "USERNAME", nullable = false, unique = true, length = 50)
	public String getUsername() {
		return this.username;
	}

	@Column(name="FULLNAME",length=50)
	public String getFullName(){
		return this.fullName;
	}
	
	@Column(name = "EMAIL", unique = true,nullable=false)
	public String getEmail() {
		return this.email;
	}

	@Column(name = "USERPAYPWD", length = 32)
	public String getUserpaypwd() {
		return this.userpaypwd;
	}

	@Column(name = "VALIDATED", length = 1)
	public Character getValidated() {
		return this.validated;
	}

	@Column(name = "NEUTRAL")
	public Integer getNeutral() {
		return this.neutral;
	}

	public void setNeutral(Integer neutral) {
		this.neutral = neutral;
	}

	@Column(name = "DRAW", length = 65535)
	public String getDraw() {
		return this.draw;
	}

	public void setDraw(String draw) {
		this.draw = draw;
	}

	@Column(name = "SEX")
	public Boolean getSex() {
		return this.sex;
	}

	@Column(name = "PHOTO")
	public String getPhoto() {
		return this.photo;
	}

	@Column(name = "COUNTRY", length = 10)
	public String getCountry() {
		return this.country;
	}

	@Column(name = "STATE", length = 20)
	public String getState() {
		return this.state;
	}

	@Column(name = "CITY", length = 20)
	public String getCity() {
		return this.city;
	}

	@Column(name = "ADDRESS")
	public String getAddress() {
		return this.address;
	}

	@Column(name = "BALANCE", precision = 22, scale = 0)
	public Double getBalance() {
		return this.balance;
	}

	@Column(name = "EXCHANGE")
	public Integer getExchange() {
		return this.exchange;
	}

	@Temporal(TemporalType.DATE)
	@Column(name = "REGDATE", length = 0)
	public Date getRegdate() {
		return this.regdate;
	}

	@Temporal(TemporalType.DATE)
	@Column(name = "UPDATEDATE", length = 0)
	public Date getUpdatedate() {
		return this.updatedate;
	}

	public void setUpdatedate(Date updatedate) {
		this.updatedate = updatedate;
	}

	@Column(name = "GOOD")
	public Integer getGood() {
		return this.good;
	}

	@Column(name = "BAD")
	public Integer getBad() {
		return this.bad;
	}

	@Temporal(TemporalType.DATE)
	@Column(name = "LASTLOGINDATE", length = 0)
	public Date getLastlogindate() {
		return this.lastlogindate;
	}

	@Column(name = "LOGINS")
	public Integer getLogins() {
		return this.logins;
	}

	@Column(name = "enabled")
	public boolean isEnabled() {
		return enabled;
	}
	
	public void setUsername(String username) {
		this.username = username;
	}

	public void setFullName(String fullName){
		this.fullName=fullName;
	}
	
	public void setConfirmPassword(String confirmPassword) {
		this.confirmPassword = confirmPassword;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public void setUserpaypwd(String userpaypwd) {
		this.userpaypwd = userpaypwd;
	}

	public void setValidated(Character validated) {
		this.validated = validated;
	}

	public void setSex(Boolean sex) {
		this.sex = sex;
	}

	public void setPhoto(String photo) {
		this.photo = photo;
	}

	public void setCountry(String country) {
		this.country = country;
	}

	public void setState(String state) {
		this.state = state;
	}

	public void setCity(String city) {
		this.city = city;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public void setBalance(Double balance) {
		this.balance = balance;
	}

	public void setExchange(Integer exchange) {
		this.exchange = exchange;
	}

	public void setGood(Integer good) {
		this.good = good;
	}

	public void setRegdate(Date regdate) {
		this.regdate = regdate;
	}

	public void setBad(Integer bad) {
		this.bad = bad;
	}

	public void setLastlogindate(Date lastlogindate) {
		this.lastlogindate = lastlogindate;
	}

	public void setLogins(Integer logins) {
		this.logins = logins;
	}
	
	public void setPassword(String password) {
        this.password = password;
    }
	
	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
	public Set<Inquire> getInquires() {
		return this.inquires;
	}

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
	public Set<Shop> getShops() {
		return this.shops;
	}

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
	public Set<Product> getProducts() {
		return this.products;
	}

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
	public Set<Favorite> getFavorites() {
		return this.favorites;
	}

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
	public Set<Auction> getAuctions() {
		return this.auctions;
	}

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user")
	public Set<Order> getOrders() {
		return this.orders;
	}

	public void setInquires(Set<Inquire> inquires) {
		this.inquires = inquires;
	}

	public void setShops(Set<Shop> shops) {
		this.shops = shops;
	}

	public void setProducts(Set<Product> products) {
		this.products = products;
	}

	public void setFavorites(Set<Favorite> favorites) {
		this.favorites = favorites;
	}

	public void setAuctions(Set<Auction> auctions) {
		this.auctions = auctions;
	}

	public void setOrders(Set<Order> orders) {
		this.orders = orders;
	}

	public boolean equals(Object o) {
		if (this == o) {
			return true;
		}
		if (!(o instanceof User)) {
			return false;
		}

		final User user = (User) o;

		return !(username != null ? !username.equals(user.getUsername()) : user
				.getUsername() != null);

	}

	public int hashCode() {
		return (username != null ? username.hashCode() : 0);
	}

	public String toString() {
		ToStringBuilder sb = new ToStringBuilder(this,
				ToStringStyle.DEFAULT_STYLE).append("username", this.username)
				.append("enabled", this.enabled);
		GrantedAuthority[] auths = this.getAuthorities();
		if (auths != null) {
			sb.append("Granted Authorities: ");
			for (int i = 0; i < auths.length; i++) {
				if (i > 0) {
					sb.append(", ");
				}
				sb.append(auths[i].toString());
			}
		} else {
			sb.append("No Granted Authorities");
		}
		return sb.toString();
	}

	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
	}

	@Transient
	public GrantedAuthority[] getAuthorities() {
		// TODO Auto-generated method stub
		return new GrantedAuthority[]{new GrantedAuthorityImpl("ROLE_ADMIN")};
	}

	@Transient
	public boolean isAccountNonLocked() {
		// TODO Auto-generated method stub
		return enabled;
	}

	@Transient
	public boolean isCredentialsNonExpired() {
		// TODO Auto-generated method stub
		return enabled;
	}

	@Transient
    public boolean isAccountExpired() {
        return enabled;
    }

	@Transient
	public boolean isAccountNonExpired() {
		// TODO Auto-generated method stub
		return enabled;
	}
}
